# coding: utf-8

# 作者：雪山凌狐
# 代码功能：基于人工智能的方法智能生成句子

import random 
from icecream import ic

rules = """
复合句子 = 句子 , 连词 复合句子 | 句子
连词 = 而且 | 但是 | 不过
句子 = 主语 谓语 宾语
主语 = 你| 我 | 他 
谓语 = 吃| 玩 
宾语 = 桃子| 皮球
    
"""

def get_grammer_by_rules(rules):
    """
    这一函数是解析预设的规则 rules
    对于随机选取的使用 | 分隔
    对于需要循环获取的，使用空格分隔
    """
    # 按行解析规则，然后再按等号分割元素，运行后结果会变为一个大的 list，内部每一个 list 元素是一行的内容
    # if r.strip() 条件可以不处理空行
    rules_row = [r.split('=') for r in rules.split('\n') if r.strip()]
    # 大的 list，里面每个元素是一个元组，元素第一个元素为规则关键词，第二个关键词为按 | 分隔的具体词语
    keyword_with_content = [(k, c.split('|')) for k, c in rules_row]
    # 将前面的 list 解析为字典，字典的键为规则关键词，字典的值为列表，列表的元素为之前按 | 分隔的内容
    # 需知有部分行是没有 | 的，这些行的值也是规则关键词，后续使用空格隔开来循环获取内容用的
    grammer = {k.strip(): [this_v.strip() for this_v in v] for k, v in keyword_with_content}

    return grammer

def generate_by_grammer(grammer, keyword='句子'):
    """生成句子的函数，通过传入解析后的规则和关键词来获取随机句子结果"""
    # 后续要用到递归，所以这里要设定递归结束点，也就是当关键词没在规则中时直接返回结果
    # 比如已经取到词 “皮球”，则直接返回 “皮球”
    if keyword not in grammer: return keyword

    # 递归调用，如果关键词在规则中则进行递归循环
    # 等价代码：
    '''
    result = []
    # 这个位置的 split 就是按空格进行分割了
    for k in random.choice(grammer[target]).split():
        # 递归调用本函数
        x = generate_by_grammer(grammer, k)
        result.append(x)
    # 将每一部分合成并返回结果
    return ''.join(result)
    '''
    return ''.join([generate_by_grammer(grammer, k) for k in random.choice(grammer[keyword]).split()])
    '''
    举例：
    比如 keyword 传入 '复合句子'，那么语法规则要么是 句子 , 连词 复合句子 的形式，要么是 句子 的形式
    如果是后者，则会看句子有哪些维度，发现有 主语 谓语 宾语 维度，这几个都是空格分隔的
    所以递归后，再次切分循环去获取，比如主语获取到 “我”，谓语获取到 “吃”，宾语获取到 “皮球”
    此时 “句子” 规则循环完毕，返回结果 “我吃皮球”。
    如果是前者，空格拆分后循环，先获取一个 “句子”，比如获取到了 “我吃皮球”
    然后第二个是一个逗号 , ，这个在关键词里没有，所以直接返回逗号
    然后第三个是连词，从连词词库中获取到一个连词比如 “而且”
    第四个是复合句子，这时又去找复合句子的类型有两种：句子 , 连词 复合句子 的形式 以及 句子 的形式
    第四部分的获取就重新进入前面讲的内容循环了，所以理论上如果一直随机取到 句子 , 连词 复合句子 的形式，最终结果会无限循环下去
    那如果获取到再生成一个 句子，那整个结果获取就结束了，最终输出结果
    '''


if __name__ == '__main__':
    # 解析规则
    grammer = get_grammer_by_rules(rules)
    # 生成句子
    for _ in range(10):
        # ic 命令是用来增强型输出结果的，可以理解为 print 的增强版
        ic(generate_by_grammer(grammer, keyword='复合句子'))
